package com.xsd.juc;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @Description: 集合类
 * @Author: zhoufuzong
 * @Created: 2021-01-01 18:17:52
 * @Version: 1.1.0
 */


/**
 * 题目： 请举例说明集合类是不安全
 *
 * 1 故障现象
 *      java.util.ConcurrentModificationException
*      2.导致原因
 *
 *      3.1 解决方案
 *          1.Vector
 *          2.Collections.synchronizedList(new ArrayList<>();
 *          3.CopyOnWriteArrayList()
 *
 *
 *      4. 优化建议（同样的错误，不出现第2次）
 *
 */
public class NotSafeDeom {

    public static void main(String[] args) {

       Map<String,String> map = new ConcurrentHashMap<>();// Collections.synchronizedMap();new HashMap<>();
//
//       Map<String,String> map1 =new HashMap<>(1000);



        for (int i = 0; i <30 ; i++) {
            new Thread(()->{
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }

       /* new HashMap<>();
        等价于 new HashMap(16,0.75)  hashMap 扩容为1倍，arrayList 为1.5倍
           put 的时候 ，先比较hash值，若相同，则比较equals,若相同，则当前位置上形成单向链表，新值在上，长度达到8，改为红黑树

        */

    }

    public void setNotSafe(){
        // HashSet 底层是一个HashMap,add的是key,value是一个present object 常量对象

        Set<String> set =  new CopyOnWriteArraySet<>() ; // new HashSet() // Collections.synchronizedSet()

        for (int i = 0; i <30 ; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();


        }
    }

    public void  listNotSafe(){
        //new Vector // new ArrayList
        //Collections.synchronizedList(new ArrayList<>());  // 小范围的数据
        List<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i <30 ; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();


        }


    }
}

/**
 *  写时复制
 *  CopyOnWrite 容器即写时复制的容器。往一个容器添加元素的时候，不直接往当前容器Object[]添加，而是先将当前Object[]进行copy
 *  复制出一个新的容器Object[] new Elements,然后新的容器Object[] newElements 里添加元素，添加完元素之后，
 *  再将原容器的引用指向新的容器 setArray(new Elements); 这样做的好处是可以对copyOnwirte 容器进行并发的读，
 *  而需要加锁，因为当前容器不会添加任何元素。所以copyOnWrite 容器也是一种读写分离的思想，读和写不同的容器。
 */
